# Поведенческий шаблон проектирования ("Команда")
# Позволяет использовать объект для инкапсуляции всей информации, необходимой для выполнения действий и вызовов позже

import abc
import typing


class ICommand(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def positive(self):
        pass

    @abc.abstractmethod
    def negative(self):
        pass


class Conveyor:
    def on(self):
        print('Конвейр запущен')

    def off(self):
        print('Конвейр остановлен')

    def speed_increase(self):
        print('Увеличить скорость')

    def speed_decrease(self):
        print('Снижена скорость конвейра')


class ConveyorWorkCommand(ICommand):
    def __init__(self, conveyor: Conveyor):
        self.conveyor: Conveyor = conveyor

    def positive(self):
        self.conveyor.on()

    def negative(self):
        self.conveyor.off()


class ConveyorAjustCommand(ICommand):
    def __init__(self, conveyor: Conveyor):
        self.conveyor: Conveyor = conveyor

    def positive(self):
        self.conveyor.speed_increase()

    def negative(self):
        self.conveyor.speed_decrease()


class Multipult:
    def __init__(self):
        self.__commands: typing.List[ICommand] = [None, None]
        self.__history: typing.Deque[ICommand] = []

    def set_command(self, button: int, command: ICommand):
        self.__commands[button] = command

    def press_on(self, button: int):
        self.__commands[button].positive()
        self.__history.append(
            self.__commands[button]
        )

    def press_cancel(self):
        if len(self.__history) != 0:
            self.__history.pop().negative()


if __name__ == '__main__':
    conveyor = Conveyor()
    multipult = Multipult()
    multipult.set_command(
        0, ConveyorWorkCommand(conveyor)
    )
    multipult.set_command(
        1, ConveyorAjustCommand(conveyor)
    )
    multipult.press_on(0)
    multipult.press_on(1)
    multipult.press_cancel()
    multipult.press_cancel()

    # Конвейр запущен
    # Увеличить скорость
    # Снижена скорость конвейра
    # Конвейр остановлен
